package ch.cryptobox.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.AbstractButton;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import ch.cryptobox.MessageBus;
import ch.cryptobox.filehandles.FileHandleI;
import ch.cryptobox.serivces.RemoteFileService;

public class NFSNavigatorGUI extends JFrame implements MouseListener
{
	private static final long serialVersionUID = 617815766344533431L;
	private static final ImageIcon folderIcon=new ImageIcon("../../crypto-box/img/folder.png");
	private static final ImageIcon fileIcon=new ImageIcon("../../crypto-box/img/file.png");

	//private final SynchronizationService nfs;
	private FileHandleI currentDir;
	private final String localMountPoint;

	private final JPanel files;
	private final JTextField path;

	public NFSNavigatorGUI(final RemoteFileService nfs, final String localMountPoint)	
	{
		super("NFS Navigator");
		path=new JTextField();
		path.setEditable(false);
		this.localMountPoint=localMountPoint;

		//this.nfs = nfs;
		currentDir= nfs.getRootHandle();

		setSize(800, 600);
		//createNodes(top);
		files=new JPanel();
		final GridBagLayout g=new GridBagLayout();
		files.setLayout(g);

		this.getContentPane().setLayout(new BorderLayout());

		final JScrollPane scroll = new JScrollPane(files);
		this.getContentPane().add(scroll,BorderLayout.CENTER);

		final JPanel north=new JPanel();
		north.setLayout(new BorderLayout());
		north.add(path,BorderLayout.CENTER);

		final JButton refresh=new JButton(new ImageIcon("../../crypto-box/img/refresh.png"));
		refresh.addMouseListener(new MouseListener() {
			@Override
			public void mouseReleased(final MouseEvent e) {}
			@Override
			public void mousePressed(final MouseEvent e) {
				NFSNavigatorGUI.this.displayAll();
			}
			@Override
			public void mouseExited(final MouseEvent e) {}
			@Override
			public void mouseEntered(final MouseEvent e) {}
			@Override
			public void mouseClicked(final MouseEvent e) {}
		});
		north.add(refresh,BorderLayout.WEST);

		final JButton back=new JButton(new ImageIcon("../../crypto-box/img/back.png"));
		back.addMouseListener(new MouseListener() {
			@Override
			public void mouseReleased(final MouseEvent e) {}
			@Override
			public void mousePressed(final MouseEvent e) {
				NFSNavigatorGUI.this.changeDir("..");
			}
			@Override
			public void mouseExited(final MouseEvent e) {}
			@Override
			public void mouseEntered(final MouseEvent e) {}
			@Override
			public void mouseClicked(final MouseEvent e) {}
		});
		north.add(back,BorderLayout.EAST);

		this.getContentPane().add(north,BorderLayout.NORTH);

		displayAll();
		setVisible(true);

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	private void displayAll()
	{
		files.removeAll();

		final GridBagConstraints c=new GridBagConstraints();
		c.gridx=0;
		c.gridy=0;
		int i=0;
		for(final FileHandleI f: currentDir.getFiles()){
			final GUIFile file=new GUIFile(f);
			file.addMouseListener(this);

			c.gridx=i%2;
			c.gridy=i/2;

			files.add(file,c);

			++i;
		}

		path.setText(currentDir.getPath());

		this.repaint();
		this.validate();
	}

	private void changeDir(final String name)
	{
		final FileHandleI tmp=currentDir.getFile(name);
		if(tmp==null) return;

		currentDir=tmp;
		displayAll();
	}

	private static class GUIFile extends JButton
	{

		private static final long serialVersionUID = 1L;
		private final FileHandleI handle;
		public GUIFile(final FileHandleI f)
		{
			super(f.getName(),f.isDirectory()?folderIcon:fileIcon);
			this.handle=f;
			this.setPreferredSize(new Dimension(100, 100));
			setVerticalTextPosition(AbstractButton.BOTTOM);
			setHorizontalTextPosition(AbstractButton.CENTER);
			setBackground(new Color(0, 0, 0, 0));
			if(!handle.isDirectory())
				setToolTipText("Restore " + handle.getName());
			else {
				setToolTipText("Enter " + handle.getName());
			}
		}

		public FileHandleI getFile()
		{
			return handle;
		}
	}

	@Override
	public void mouseClicked(final MouseEvent e) {
		final GUIFile file=(GUIFile) e.getSource();
		switch(e.getButton())
		{
		case MouseEvent.BUTTON1:
			if(file.getFile().isDirectory())
				changeDir(file.getFile().getName());
			else
				restore(file.getFile());
		}
	}

	public boolean restore(final FileHandleI file) {		
		final byte[] data = file.download();

		if(null == data) {
			return false;
		} else {
			try {
				//System.out.println(localMountPoint + file.getPath());
				final File localFile = new File(localMountPoint + file.getPath());
				final File parent = new File(localFile.getParent());

				if(!parent.exists()) {
					MessageBus.getInstance().addToBeIgnoredOnce(parent.getPath());
					parent.mkdirs();
				} else {
					MessageBus.getInstance().addToBeIgnoredOnce(localFile.getPath());
				}

				final FileOutputStream writer = new FileOutputStream(localFile);
				writer.write(data);
			} catch (final IOException e) {

				e.printStackTrace();
				return false;
			}

			return true;
		}
	}

	@Override
	public void mousePressed(final MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseReleased(final MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseEntered(final MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(final MouseEvent e) {
		// TODO Auto-generated method stub

	}
}